package dao

import (
	"context"
	"fmt"
	"log"
	"time"

	"gitee.com/zhaokangming/tiny-ticktok/model"
	"gitee.com/zhaokangming/tiny-ticktok/pkg/constants"

	"github.com/go-redis/redis/v8"
	"github.com/json-iterator/go"
	"gorm.io/gorm"
)

// Video 影音视频字段
type Video struct {
	gorm.Model
	Title    string `gorm:"column:title"`
	AuthorID int64  `gorm:"column:uid"`
	PlayUrl  string `gorm:"column:play_url"`
	CoverUrl string `gorm:"column:cover_url"`
}

func (m *Video) TableName() string {
	return constants.VideoTableName
}

func CreateVideo(ctx context.Context, video Video) error {
	return DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.WithContext(ctx).Create(&video).Error; err != nil {
			return err
		}

		var json = jsoniter.ConfigCompatibleWithStandardLibrary
		val, err := json.Marshal(video)
		if err != nil {
			return err
		}
		// 同步放入redis缓存中
		if err := RDB.ZAdd(ctx, "videoZSet", &redis.Z{
			Score:  float64(video.CreatedAt.Unix()),
			Member: val,
		}).Err(); err != nil {
			return err
		}
		return RDB.Del(ctx, "videosCache", fmt.Sprintf("videoCache:%d", video.AuthorID)).Err()
	})
}

// MGetVideos 按照时间戳降序查找所有视频
func MGetVideos(ctx context.Context, nextTime int64) ([]Video, error) {
	var res []Video
	// 根据时间戳来降序显示视频
	if err := DB.WithContext(ctx).Order("created_at DESC").Where("created_at < FROM_UNIXTIME(?)", nextTime).
		Limit(30).Find(&res).Error; err != nil {
		return res, err
	}

	return res, nil
}

// MGetVideosFromRedis 按照时间戳降序查找所有视频
func MGetVideosFromRedis(ctx context.Context) ([]Video, error) {
	res := make([]Video, 0, 30)
	// 根据ZSet时间戳来降序显示视频
	idList, err := RDB.ZRevRange(ctx, "videoZSet", 0, 30).Result()
	if err != nil {
		return nil, err
	}

	// 再通过redis string 解码取出
	for _, v := range idList {
		var video Video

		var json = jsoniter.ConfigCompatibleWithStandardLibrary
		err := json.Unmarshal([]byte(v), &video)
		if err != nil {
			log.Printf("缓存json解码失败！")
		}
		res = append(res, video)
	}
	return res, nil
}

func MGetVideosByUID(ctx context.Context, uid int64) ([]Video, error) {
	var res []Video
	if err := DB.WithContext(ctx).Where("uid = ?", uid).Find(&res).Error; err != nil {
		return res, err
	}

	return res, nil
}

func MGetVideosByIDs(ctx context.Context, vids []int64) ([]Video, error) {
	var res []Video
	if err := DB.WithContext(ctx).Where("id in ?", vids).Find(&res).Error; err != nil {
		return res, err
	}

	return res, nil
}

// SetEXOfVideos 将视频切片对象转化为json并存到redis中,并设置过期时间
func SetEXOfVideos(ctx context.Context, videoList []model.Video, key string, expiration time.Duration) error {
	// 对视频列表切片json序列化
	var json = jsoniter.ConfigCompatibleWithStandardLibrary
	bytes, err := json.Marshal(videoList)

	if err != nil {
		return err
	} else {
		cache := string(bytes)
		// 设置过期时间为30分钟
		RDB.SetEX(ctx, key, cache, expiration)
		if err != nil {
			log.Printf("视频列表缓存设置失败！！！")
		}
	}
	return nil
}
